package elephant.servers.gameserver.session;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elephant.servers.gameserver.codec.ResponseMessage;
import elephant.servers.gameserver.core.GameRoom;
import io.netty.channel.Channel;

/**
 * 
 * @author icecooly
 *
 */
public class GameSession {
	private static Logger logger=LoggerFactory.getLogger(GameSession.class);
	//
	private Channel channel;
	private String principal;
	private int id;
	private boolean isActive;
	private Object userObject;
	private String remoteHost;
	private String userAgent;
	private int remotePort;
	private long createTime;
	private long lastAccessTime;
	private int currentRequestId;
	private Set<String>joinRoomList;
	private short bodySerializeType;
	//
	public GameSession(Channel channel){
		this.channel=channel;
		//
		SocketAddress remoteAddr=channel.remoteAddress();
		remoteHost="<UNKNOW>";
		if(remoteAddr!=null){
			InetSocketAddress addr=(InetSocketAddress) remoteAddr;
			InetAddress ad=addr.getAddress();
			if(ad!=null){
				remoteHost=ad.getHostAddress();
				remotePort=addr.getPort();
			}
		}
		createTime=lastAccessTime=System.currentTimeMillis();
		joinRoomList=new TreeSet<String>();
	}
	//--------------------------------------------------------------------------
	/**
	 * 
	 */
	public void push(String serviceId,Object body){
		if(body==null){
			throw new IllegalArgumentException("body can not be null.");
		}
		ResponseMessage rsp=new ResponseMessage();
		rsp.requestId=0;
		rsp.serviceId=serviceId;
		rsp.bodySerializeType=bodySerializeType;
		rsp.body=body;
		writeResponseMessage(rsp);
	}
	/**
	 * 
	 */
	
	public void kick(String msg){
		if(logger.isDebugEnabled()){
			logger.debug("session kicked:"+msg);
		}
		sendError(ResponseMessage.ERR_CODE_KICKED, msg);
		if(channel!=null){
			channel.close();	
		}
	}
	//
	public void sendError(int code,String msg){
		ResponseMessage rspMessage=new ResponseMessage();
		rspMessage.errCode=code;
		rspMessage.errMsg=msg;
		rspMessage.bodySerializeType=bodySerializeType;
		rspMessage.requestId=currentRequestId;
		writeResponseMessage(rspMessage);
	}
	//
	//---------------------------room---------------------------------------------
	public void joinRoom(GameRoom room){
		joinRoomList.add(room.getId());
	}
	
	public void  leaveRoom(GameRoom room){
		joinRoomList.remove(room.getId());
	}
	
	public List<String>getJoinRooms(){
		return new ArrayList<>(joinRoomList);
	}
	//---------------------------------------------------------------------------
	public void writeResponseMessage(ResponseMessage rsp){
		if(channel!=null){
			channel.writeAndFlush(rsp);
		}else{
			logger.warn("writeResponseMessage failed.null channel");
		}
	}
	//
	public void setId(int id){
		this.id=id;
	}
	
	public void setPrincipal(String principal) {
		this.principal = principal;
	}
	
	public long getLastAccessTime() {
		return lastAccessTime;
	}
	
	public boolean isActive() {
		return isActive;
	}
	
	public void setActive(boolean isActive) {
		this.isActive = isActive;
	}
	
	public Object getUserObject() {
		return userObject;
	}
	
	public void setUserObject(Object userObject) {
		this.userObject = userObject;
	}
	
	public String getPrincipal() {
		return principal;
	}
	
	public int getId() {
		return id;
	}
	
	public String getRemoteHost() {
		return remoteHost;
	}
	
	public int getRemotePort() {
		return remotePort;
	}
	
	public long getCreateTime() {
		return createTime;
	}

	public void updateLastAccessTime(){
		lastAccessTime=System.currentTimeMillis();
	}
	
	public String getUserAgent() {
		return userAgent;
	}
	
	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}
	
	public boolean equals(Object anObject) {
		if(anObject==null||!(anObject instanceof GameSession)){
			return false;
		}
		return id==((GameSession)anObject).id;
	}
	public short getBodySerializeType() {
		return bodySerializeType;
	}
	public void setBodySerializeType(short bodySerializeType) {
		this.bodySerializeType = bodySerializeType;
	}
}
